`include "vsrc/ysyx_20220337_define.v"

module ysyx_20220337_EXU (
    input   [4:0]    ALU_control,
    input            op_dw,//rv64
    input   [63:0]   data1,
    input   [63:0]   data2,
    input            jump,
    output  [63:0]   ALU_result,
    output           branch
    //output           NOT_ZERO
);
wire NOT_ZERO;
wire [63:0] ALU_result_before;
assign NOT_ZERO = ALU_result == 64'b0 ? 1'b0 : 1'b1;
assign branch = jump & NOT_ZERO;
assign ALU_result = op_dw? {{32{ALU_result_before[31]}},ALU_result_before[31:0]} : ALU_result_before;

assign ALU_result_before = (ALU_control == `ysyx_20220337_add) ? data1 + data2 :
                    (ALU_control == `ysyx_20220337_sub) ? data1 - data2 :
                    (ALU_control == `ysyx_20220337_and) ? data1 & data2 :
                    (ALU_control == `ysyx_20220337_or)  ? data1 | data2 :
                    (ALU_control == `ysyx_20220337_xor) ? data1 ^ data2 :
                    (ALU_control == `ysyx_20220337_sl)  ? data1 << data2[5:0] :
                    (ALU_control == `ysyx_20220337_sr)  ? {{32{1'b0}},data1[31:0]} >> data2[5:0] :
                    (ALU_control == `ysyx_20220337_sla) ? data1 <<< data2[5:0] :
                    (ALU_control == `ysyx_20220337_sra) ? data1 >>> data2[5:0] :
                    (ALU_control == `ysyx_20220337_slt) ? ($signed(data1) < $signed(data2)? 64'b1 : 64'b0) :
                    (ALU_control == `ysyx_20220337_sltu) ? (data1 < data2 ? 64'b1 : 64'b0) :
                    (ALU_control == `ysyx_20220337_sge) ? ($signed(data1) >= $signed(data2)? 64'b1 : 64'b0) :
                    (ALU_control == `ysyx_20220337_sgeu) ? (data1 >= data2 ? 64'b1 : 64'b0) :
                    (ALU_control == `ysyx_20220337_seq) ? (data1 == data2 ? 64'b1 : 64'b0) :
                    (ALU_control == `ysyx_20220337_sne) ? (data1 != data2 ? 64'b1 : 64'b0) :
                    (ALU_control == `ysyx_20220337_mul) ? $signed(data1) * $signed(data2) :
                    (ALU_control == `ysyx_20220337_mulh) ? data1[63:32] * data2[63:32] :
                    (ALU_control == `ysyx_20220337_mulhu) ? data1 * data2 :
                    (ALU_control == `ysyx_20220337_mulhsu) ? $signed(data1) * data2 :
                    (ALU_control == `ysyx_20220337_div) ? $signed(data1) / $signed(data2) :
                    (ALU_control == `ysyx_20220337_divu) ? data1 / data2 :
                    (ALU_control == `ysyx_20220337_rem) ? $signed(data1) % $signed(data2) :
                    (ALU_control == `ysyx_20220337_remu) ? data1 % data2 :
                    64'b0;

endmodule